home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-06-28 | 12.1 KB | 570 lines | [TEXT/CWIE] |
- /*
- File: Text2Something.cp
-
- Contains: Sample Contextual Menu plugin
-
- Written by: Kevin Hewitt & Tim Knox
-
- Copyright:
-
- */
-
-
- // Class Header
- #include "Text2Something.h"
-
- // Mac OS Includes
- #include <AERegistry.h>
- #include <CodeFragments.h>
- #include <ContextualMenuPlugins.h>
- #include <Files.h>
- #include <TextEdit.h>
- #include <TextUtils.h>
- #include <Folders.h>
- // Utilities
-
- // SOM Includes
- #include <som.xh>
-
- enum
- {
- kBeautifyCommand = 100,
- kUglifyCommand = 101
- };
-
- enum
- {
- kFT_Unknown = 0,
- kFT_Mac,
- kFT_Dos
- };
-
- // Function declarations
- extern pascal OSErr __initialize(CFragInitBlockPtr); // MetroWerks's default initializer
- extern pascal void __terminate(void);
- pascal OSErr Text2SomethingInitialize(CFragInitBlockPtr init); // our initializer
-
- OSStatus AddCommandToAEDescList(ConstStr255Param inCommandString,
- SInt32 inCommandID, AEDescList* ioCommandList);
- OSErr CoerceFiles(AEDescList* inFileList, SInt32 inCommandID);
- OSErr CoerceFile(FSSpec* file, SInt32 inCommandID);
- void Beautify (char * inp, char * outp, long * size, long * bytesParsed);
- void Uglify (char * inp, char * outp, long * size, long * bytesParsed);
- void CheckFile(FSSpec *inFileSpec, int *outFileType);
-
-
-
- // ---------------------------------------------------------------------------
- // Text2SomethingInitialize
- // ---------------------------------------------------------------------------
- // Contextual Menu Plugins must register
- // themselves in their init routine.
- // ---------------------------------------------------------------------------
-
- pascal OSErr Text2SomethingInitialize(CFragInitBlockPtr init)
- {
- #pragma unused (init)
-
- // Initialize Metrowerks library
- OSErr err = __initialize(init);
-
- // Register with SOM
- if (err == noErr)
- somNewClass(Text2Something);
-
- return err;
- }
-
-
-
- // ---------------------------------------------------------------------------
- // Text2Something::Initialize
- // ---------------------------------------------------------------------------
-
- OSStatus Text2Something::Initialize(
- Environment*,
- FSSpec* inFileSpec)
- {
- #pragma unused (inFileSpec)
- return noErr;
- }
-
-
-
- // ---------------------------------------------------------------------------
- // Text2Something::ExamineContext
- // ---------------------------------------------------------------------------
-
- OSStatus Text2Something::ExamineContext(
- Environment*,
- AEDesc *inContextDescriptor,
- SInt32 inTimeOutInTicks,
- AEDescList* ioCommands,
- Boolean* outNeedMoreTime)
- {
- #pragma unused(inTimeOutInTicks)
-
- OSStatus err = noErr;
-
- // Make sure the descriptor isn't null
- if (inContextDescriptor != NULL)
- {
- AEDesc fileDesc = { typeNull, NULL };
-
- do
- {
- // Try to get an FSSpec out of the context descriptor; make sure to
- // coerce it, cuz the app may have passed an object specifier.
- err = ::AECoerceDesc(inContextDescriptor, typeFSS, &fileDesc);
- if (err != noErr) break;
-
- // pull the FSSpec out of the descriptor
- FSSpec theFileSpec;
- ::BlockMoveData(*fileDesc.dataHandle, &theFileSpec,
- ::GetHandleSize(fileDesc.dataHandle));
-
- // get the Catalog Info for this file
- CInfoPBRec theInfo;
- theInfo.hFileInfo.ioCompletion = NULL; // synchronous
- theInfo.hFileInfo.ioNamePtr = theFileSpec.name;
- theInfo.hFileInfo.ioVRefNum = theFileSpec.vRefNum;
- theInfo.hFileInfo.ioFDirIndex = 0; // search for the named item
- theInfo.hFileInfo.ioDirID = theFileSpec.parID;
- err = ::PBGetCatInfoSync(&theInfo);
- if (err != noErr) break;
-
- // see if we have a file and not a folder
- if ((theInfo.hFileInfo.ioFlAttrib & ioDirMask) == 0)
- {
- // Check the file's suffix
- OSType suffix = 0;
- OSType fileType = theInfo.hFileInfo.ioFlFndrInfo.fdType;
- OSType fileCreator = theInfo.hFileInfo.ioFlFndrInfo.fdCreator;
- if (*theInfo.hFileInfo.ioNamePtr > 3)
- {
- suffix = *(OSType*)&theInfo.hFileInfo.ioNamePtr[*theInfo.hFileInfo.ioNamePtr - 3];
- ::UppercaseText((Ptr) &suffix, 4, smSystemScript);
- }
-
- if (suffix == '.TXT' || fileType == 'TEXT')
- {
- int fileType;
- // Add this command to the command list
- CheckFile(&theFileSpec, &fileType);
- switch (fileType)
- {
- case kFT_Unknown:
- break;
- case kFT_Mac:
- err = ::AddCommandToAEDescList("\pUglify", kUglifyCommand, ioCommands);
- break;
- case kFT_Dos:
- err = ::AddCommandToAEDescList("\pBeautify", kBeautifyCommand, ioCommands);
- break;
- }
- if (err != noErr) break;
- }
- }
- }
- while (false);
-
- // clean up after ourself
- ::AEDisposeDesc(&fileDesc);
- }
-
- *outNeedMoreTime = false;
-
- return err;
- }
-
-
-
- // ---------------------------------------------------------------------------
- // Text2Something::HandleSelection
- // ---------------------------------------------------------------------------
-
- OSStatus Text2Something::HandleSelection(
- Environment*,
- AEDesc *inContextDescriptor,
- SInt32 inCommandID)
- {
- #pragma unused (inContextDescriptor, inCommandID)
-
- // here is where you would actually carry out the action that the user
- // requested.
-
- return CoerceFiles(inContextDescriptor, inCommandID);
- // return noErr;
- }
-
-
-
- // ---------------------------------------------------------------------------
- // Text2Something::PostMenuCleanup
- // ---------------------------------------------------------------------------
-
- OSStatus Text2Something::PostMenuCleanup(
- Environment*)
- {
- // Nothing to clean up here
-
- return noErr;
- }
-
-
-
- // ---------------------------------------------------------------------------
- // AddCommandToAEDescList
- // ---------------------------------------------------------------------------
-
- OSStatus AddCommandToAEDescList(
- ConstStr255Param inCommandString,
- SInt32 inCommandID,
- AEDescList* ioCommandList)
- {
- OSStatus theError = noErr;
-
- AERecord theCommandRecord = { typeNull, NULL };
-
- do
- {
- // create an apple event record for our command
- theError = ::AECreateList(NULL, 0, true, &theCommandRecord);
- if (theError != noErr) break;
-
- // stick the command text into the aerecord
- theError = ::AEPutKeyPtr(&theCommandRecord, keyAEName, typeChar,
- &inCommandString[1], inCommandString[0]);
- if (theError != noErr) break;
-
- // stick the command ID into the AERecord
- theError = ::AEPutKeyPtr(&theCommandRecord, keyContextualMenuCommandID, typeLongInteger,
- &inCommandID, sizeof (inCommandID));
- if (theError != noErr) break;
-
- // stick this record into the list of commands that we are passing back to CMM
- theError = ::AEPutDesc(ioCommandList, // the list we're putting our command into
- 0, // stick this command onto the end of our list
- &theCommandRecord); // the command I'm putting into the list
-
- } while (false);
-
- // clean up after ourself; dispose of the AERecord
- ::AEDisposeDesc(&theCommandRecord);
-
- return theError;
- }
-
- OSErr CoerceFiles(AEDescList* inFileList, SInt32 inCommandID)
- {
- long items, x;
- AEDesc fileDesc = { typeNull, NULL };
- AEKeyword returnedKeyword;
- FSSpec theFileSpec;
- OSErr err;
-
- ::AECountItems(inFileList, &items);
- for (x=1; x<= items; x++)
- {
- ::AEGetNthDesc(inFileList, x, typeFSS, &returnedKeyword, &fileDesc);
- ::BlockMoveData(*fileDesc.dataHandle, &theFileSpec, ::GetHandleSize(fileDesc.dataHandle));
- err = CoerceFile(&theFileSpec, inCommandID);
- ::AEDisposeDesc(&fileDesc);
- if (err != noErr)
- break;
- }
- return err;
- }
-
-
-
-
- OSErr CoerceFile(FSSpec* inFileSpec, SInt32 inCommandID)
- {
- short inref, outref;
- long insz, outsz, intotsz = 0;
- short foundvol;
- long founddir;
- long prevFilePos;
- long bytesParsed;
- long bytesWritten;
- FSSpec outfs;
-
- OSErr anErr = FindFolder (0, kDesktopFolderType, true, &foundvol, &founddir);
- if (anErr != noErr)
- goto GotAnError;
-
- anErr = FSMakeFSSpec (foundvol, founddir, "\ptemp work file", &outfs);
- if (anErr != noErr) {
- if (anErr != fnfErr)
- goto GotAnError;
- anErr = FSpCreate (&outfs, 'R*ch', 'TEXT', 0);
- if (anErr != noErr)
- goto GotAnError;
- };
-
- Handle inwork, outwork;
- inwork = NewHandle (4096L);
- outwork = NewHandle (4096L);
-
- HLockHi (inwork);
- HLockHi (outwork);
-
- anErr = FSpOpenDF (inFileSpec, fsRdPerm, &inref);
- if (anErr != noErr)
- goto GotAnError;
-
- anErr = FSpOpenDF (&outfs, fsWrPerm, &outref);
- if (anErr != noErr)
- goto GotAnError;
-
- anErr = GetEOF (inref, &intotsz);
- if (anErr != noErr)
- goto GotAnError;
-
- prevFilePos = 0L;
- bytesWritten = 0L;
- while (intotsz > 0) {
- insz = 2048L;
- anErr = FSRead (inref, &insz, *inwork);
- if ((anErr != noErr) && (anErr != eofErr))
- break;
- outsz = insz;
- switch (inCommandID)
- {
- case kBeautifyCommand:
- Beautify (*inwork, *outwork, &outsz, &bytesParsed);
- break;
- case kUglifyCommand:
- Uglify (*inwork, *outwork, &outsz, &bytesParsed);
- break;
- }
- prevFilePos += bytesParsed;
- anErr = ::SetFPos(inref, fsFromStart, prevFilePos);
- if (anErr != noErr)
- break;
- anErr = FSWrite (outref, &outsz, *outwork);
- bytesWritten += outsz;
- if (anErr != noErr)
- break;
- intotsz -= bytesParsed;
- };
- if (anErr != noErr)
- goto GotAnError;
-
- ::SetEOF(outref, bytesWritten);
- ::FSClose(outref);
- ::FSClose(inref);
- anErr = FSpExchangeFiles (inFileSpec, &outfs);
- if (anErr != noErr)
- goto GotAnError;
-
- anErr = FSpDelete (&outfs);
- if (anErr != noErr)
- goto GotAnError;
-
- GotAnError:
- if (inwork)
- DisposeHandle (inwork);
- if (outwork)
- DisposeHandle (outwork);
-
- return anErr;
- }
-
- void Beautify (char * inp, char * outp, long * size, long * bytesParsed)
- {
- char c;
- int numOfPeriods = 0;
- long savesz, curpos;
- long curOutPos;
- Boolean breaksoon, seencr, seenquote, seenstop, seenblank;
-
-
- breaksoon = seencr = seenquote = seenstop = seenblank = false;
-
- savesz = *size;
- *size = 0;
- curOutPos = *size;
- curpos = curOutPos;
- *bytesParsed = 0;
-
-
- while (curpos <= savesz) {
- c = inp [curpos++];
-
- if (c == 0x0d)
- {
- seencr = true;
- }
- else
- {
- if (seencr)
- {
- seencr = false;
- if (c == 0x0a)
- c = inp[curpos++];
- if (c == 0x0d)
- seencr = true;
- if (breaksoon)
- break;
- }
- }
-
- if (c == '"') {
- if (!seenquote)
- c = '“';
- else
- c = '”';
- seenquote = !seenquote;
- }
-
- if (c == '\'')
- c = '’';
-
- if (seenstop == true)
- {
- if (numOfPeriods == 3)
- {
- if (c != '.')
- {
- curOutPos -= 3;
- outp[curOutPos++] = '…';
- }
- seenstop = false;
- }
- }
-
- if ((seenblank) && c == ' ')
- continue;
-
- if (c == ' ')
- seenblank = true;
- else
- seenblank = false;
-
- outp [curOutPos++] = c;
-
- if (c == '.')
- {
- numOfPeriods++;
- seenstop = true;
- }
- else
- numOfPeriods = 0;
-
- if (curpos > 1920L)
- breaksoon = true;
- };
- *size = curOutPos - 1;
- *bytesParsed = curpos - 1;
-
- // if (breaksoon == true)
- // BlockMove ((inp + curpos), inp, (savesz - curpos));
- }
-
- void Uglify (char * inp, char * outp, long * size, long * bytesParsed)
- {
- char c;
- int numOfPeriods = 0;
- long savesz, curpos;
- long curOutPos;
- Boolean breaksoon, seencr, seenstop, seenblank;
-
-
- breaksoon = seencr = seenstop = seenblank = false;
-
- savesz = *size;
- *size = 0;
- curOutPos = *size;
- curpos = curOutPos;
- *bytesParsed = 0;
-
-
- while (curpos <= savesz) {
- c = inp [curpos++];
-
- if (seencr)
- {
- seencr = false;
- if (c != 0x0a)
- outp [curOutPos++] = 0x0a;
- if (breaksoon)
- break;
- }
- if (c == 0x0d)
- {
- seencr = true;
- }
-
- if (c == '“')
- c = '"';
- if (c == '”')
- c = '"';
-
- if (c == '’')
- c = '\'';
-
- if (c == '…')
- {
- outp [curOutPos++] = '.';
- outp [curOutPos++] = '.';
- outp [curOutPos++] = '.';
- continue;
- }
-
- outp [curOutPos++] = c;
-
-
- if (curpos > 1920L)
- breaksoon = true;
- };
- *size = curOutPos - 1;
- *bytesParsed = curpos - 1;
-
- // if (breaksoon == true)
- // BlockMove ((inp + curpos), inp, (savesz - curpos));
- }
-
- void CheckFile(FSSpec *inFileSpec, int *outFileType)
- {
- short refNum;
- OSErr err;
- long bytes;
- char buf[255];
- char *ptr;
- int LoopIt = 2;
-
- *outFileType = kFT_Unknown;
- err = ::FSpOpenDF(inFileSpec, fsRdPerm, &refNum);
- if (err == noErr)
- {
- do {
- LoopIt--;
- bytes = sizeof(buf);
- err = ::FSRead(refNum, &bytes, buf);
- if (err == noErr || bytes > 0)
- {
- ptr = &buf[0];
- for (; bytes; bytes--)
- {
- if (*ptr == 0x0d)
- {
- ptr++;
- if (*ptr == 0x0a)
- *outFileType = kFT_Dos;
- else
- *outFileType = kFT_Mac;
- bytes = 1;
- LoopIt = 0;
- }
- ptr++;
- }
- }
- else
- LoopIt = 0;
- } while (LoopIt);
- }
- ::FSClose(refNum);
- return;
- }